﻿using System;
using System.Linq;
using NHibernate;
using NHibernate.Cfg;
using NHibernate.Linq;

namespace MusicStore.Data.Repository
{
	/// <summary>
	/// repository implemented using NHibernate and linq to NHibernate, it's a very basic implemtation
	/// </summary>
	public class RepositoryBase : IDisposable, IRepositoryBase
	{
		/// <summary>
		/// read the nhib configuration from fine and initializa the engine
		/// 
		/// todo: refactor to use a session manager that allows session per call pattern when used in a webservice
		/// so we can remove the explicit Flush() calls
		/// </summary>
		public RepositoryBase()
		{
			var cfg = new Configuration().Configure();
			var factory = cfg.BuildSessionFactory();
			_factory = factory;
		}

		#region Dispose

		private bool _disposed;

		public void Dispose()
		{
			Dispose(true);
			GC.SuppressFinalize(this);
		}

		protected virtual void Dispose(bool disposing)
		{
			if (!_disposed)
			{
				if (disposing) // Managed:
				{
					if (_session != null)
					{
						// eventually rollback uncommitted transactions
						if ((_session.Transaction != null) && (_session.Transaction.IsActive))
							_session.Transaction.Rollback();
						_session.Flush();
						_session.Close();
					}
				}
				// Unmanaged:
			}
			_disposed = true;
		}

		~RepositoryBase()
		{
			Dispose(false);
		}

		#endregion

		public ISession Session
		{
			get
			{
				if ((_session == null) || (!_session.IsOpen))
					_session = _factory.OpenSession();
				return _session;
			}
		}
      private ISession _session;
		private readonly ISessionFactory _factory;

		#region IAlbumRepository Members

		public IQueryable<T> List<T>()
		{
			return Session.Linq<T>();
		}

		public void Save<T>(T obj)
		{
			Session.SaveOrUpdate(obj);
		}

		public void Delete<T>(T obj)
		{
			Session.Delete(obj);
		}

		public void Flush()
		{
			Session.Flush();
		}

		#endregion
	}
}
